package com.soa_back.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.soa_back.common.CommonResponse;
import com.soa_back.common.ResponseCode;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

class T{
    String name;
    T f,g;
}

@RestController
@RequestMapping("/test/")
@Validated
public class TestController {

    @GetMapping("/objectMapDemo")
    public JSONObject getObjectMapDemo(@RequestBody JSONObject requsetObj){

        System.out.println(requsetObj);

        T obj = createTObjDemo(requsetObj);
        System.out.println(obj + ", " + obj.name);
        System.out.println(obj.f + ", " + obj.f.name);
        System.out.println(obj.g + ", " + obj.g.name);
        System.out.println(obj.f.f + ", " + obj.f.f.name);
        System.out.println(obj.g.f + ", " + obj.g.f.name);

        List<Integer> idNewList = new ArrayList<>();
        List<String> objHashList = new ArrayList<>();

        JSONObject res = PointerSwizzling(obj, idNewList, objHashList); //通过id即PointerSwizzling的方式变成json对象
        System.out.println(res);

        return res;
    }

    @GetMapping("/objectMap")
    public JSONObject getObjectMap(@RequestBody JSONObject requsetObj){

//        System.out.println(requsetObj);

        List<String> idList = new ArrayList<>();
        List<T> objList = new ArrayList<>();

        T obj = createTObjByID(requsetObj, idList, objList);
        System.out.println(obj + ", " + obj.name);
        System.out.println(obj.f + ", " + obj.f.name);
        System.out.println(obj.g + ", " + obj.g.name);
        System.out.println(obj.f.f + ", " + obj.f.f.name);
        System.out.println(obj.g.f + ", " + obj.g.f.name);

        obj.f.f.g = new T(); //新加一个节点
        obj.f.f.g.name = "new point";

        List<Integer> idNewList = new ArrayList<>();
        List<String> objHashList = new ArrayList<>();

        JSONObject res = PointerSwizzling(obj, idNewList, objHashList); //通过id即PointerSwizzling的方式变成json对象
        System.out.println(res);

        return res;
    }

    public static T createTObjDemo(JSONObject jsonObject){

        T tObj = new T();

        Iterator iter = jsonObject.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            String keyStr = entry.getKey().toString();
            String valueStr = entry.getValue().toString();
            String valueJsonStr = JSON.toJSONString(entry.getValue());

            if (keyStr.equalsIgnoreCase("f")){
                tObj.f = createTObjDemo(JSONObject.parseObject(valueJsonStr));
            }else if (keyStr.equalsIgnoreCase("g")){
                tObj.g = createTObjDemo(JSONObject.parseObject(valueJsonStr));
            }else if (keyStr.equalsIgnoreCase("name")){
                tObj.name = valueStr;
            }
        }

        return tObj;
    }

    public static T createTObjByID(JSONObject jsonObject, List<String> idList, List<T> objList){

        T tObj;

        String id = jsonObject.get("id").toString();
//        System.out.println("新的遍历：" + id);
        if (idList.contains(id)){
//            System.out.println(id);
            tObj = objList.get(idList.indexOf(id));
        }else {
            idList.add(id);
            tObj = new T();
            objList.add(tObj);
//            System.out.println(tObj);
        }

        Iterator iter = jsonObject.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            String keyStr = entry.getKey().toString();
            String valueStr = entry.getValue().toString();
            String valueJsonStr = JSON.toJSONString(entry.getValue());

            if (keyStr.equalsIgnoreCase("f")){
                tObj.f = createTObjByID(JSONObject.parseObject(valueJsonStr), idList, objList);
            }else if (keyStr.equalsIgnoreCase("g")){
                tObj.g = createTObjByID(JSONObject.parseObject(valueJsonStr), idList, objList);
            }else if (keyStr.equalsIgnoreCase("name")){
                tObj.name = valueStr;
            }
        }

        return tObj;
    }

    public static JSONObject PointerSwizzling(T obj, List<Integer> idNewList, List<String> objHashList){

        JSONObject jsonObj = new JSONObject();

        String objHashCode = Integer.toHexString(obj.hashCode()); //对象的散列地址
        System.out.println(objHashCode);

        if (objHashList.contains(objHashCode)){
//            System.out.println(id);
            jsonObj.put("id", idNewList.get(objHashList.indexOf(objHashCode)));
        }else {
            int id = idNewList.size() + 1;
            idNewList.add(id);
            jsonObj.put("id", id);
            objHashList.add(objHashCode);
//            System.out.println(tObj);
        }

        if (obj.name != null){
            jsonObj.put("name", obj.name);
        }
        if (obj.f != null){
            JSONObject json = PointerSwizzling(obj.f, idNewList, objHashList);
            jsonObj.put("f", json);
        }
        if (obj.g != null){
            JSONObject json = PointerSwizzling(obj.g, idNewList, objHashList);
            jsonObj.put("g", json);
        }

        return jsonObj;
    }
}

//    public static JSONObject Serialize(T obj){
//        JSONObject jsonObj4 = new JSONObject();
//        jsonObj4.put("name", obj.f.f.name);
//        JSONObject jsonObj5 = new JSONObject();
//        jsonObj5.put("name", obj.g.f.name);
//        JSONObject jsonObj2 = new JSONObject();
//        jsonObj2.put("name", obj.f.name);
//        jsonObj2.put("f", jsonObj4);
//        JSONObject jsonObj3 = new JSONObject();
//        jsonObj3.put("name", obj.g.name);
//        jsonObj3.put("f", jsonObj5);
//        JSONObject jsonObj = new JSONObject();
//        jsonObj.put("name", obj.name);
//        jsonObj.put("f", jsonObj2);
//        jsonObj.put("g", jsonObj3);
//
//        return jsonObj;
//    }
